﻿using System;
using System.Collections.Generic;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.GamePlay;

namespace IQIGame.Onigao.Logic
{
    public class CustomPropertyComponent : TComponent
    {
        public Unit unit;
        public BattleUpdateResultContrller resultCtrl;

        public readonly Dictionary<int, TAny> propertyHash = new Dictionary<int, TAny>((int)ECustomProperty.Max);
        public readonly Dictionary<string, int> customHash = new Dictionary<string, int>();

        # region Property

        public T GetProperty<T>(ECustomProperty rType)
        {
            var nKey = (int)rType;
            return this.GetProperty<T>(nKey);
        }

        public T GetProperty<T>(int nKey)
        {
            if (this.propertyHash.TryGetValue(nKey, out var rAny))
            {
                return TAnyHelper.GetAny<T>(rAny);
            }

            return default(T);
        }

        public void SetProperty<T>(ECustomProperty rType, T rValue, ETAnyType rAnyType)
        {
            var nKey = (int)rType;
            this.SetProperty(nKey, rValue, rAnyType);
        }

        public void SetProperty<T>(int nKey, T rValue, ETAnyType rAnyType)
        {
            if (!this.TryGetPropertyAny(nKey, out var rAny))
            {
                rAny = this.AddProperty(nKey, rAnyType);
            }
            TAnyHelper.SetAny(rAny, rValue);

            if (this.resultCtrl == null)
            {
                this.resultCtrl = this.unit.battle.playCtrl.resultCtrl;
            }

            var rPOD = BattleUpdateFactory.CreateUnitCustomProperty(this.unit.GUID, nKey, rAnyType, rValue);
            this.resultCtrl.Add(rPOD);

            if (rAnyType == ETAnyType.Int32)
            {
                this.unit.battle.playCtrl.triggerCtrl.Broadcast(EBattleTriggerType.Battle_SetCustomProperty, (ECustomProperty)nKey, string.Empty, this.unit);
            }
        }

        private TAny AddProperty(int nKey, ETAnyType rAnyType)
        {
            this.propertyHash[nKey] = TAnyHelper.NewAny(rAnyType);
            return this.propertyHash[nKey];
        }

        private bool TryGetPropertyAny(int nKey, out TAny rAny)
        {
            return this.propertyHash.TryGetValue(nKey, out rAny);
        }

        public void ModifyIntProperty(ECustomProperty nKey, bool bAdd)
        {
            var nValue = this.GetProperty<int>(nKey);
            nValue = Math.Max(0, nValue + (bAdd ? 1 : -1));
            this.SetProperty(nKey, nValue, ETAnyType.Int32);
        }

        #endregion

        #region customHash

        public int GetProperty(string key)
        {
            if (this.customHash.TryGetValue(key, out var nValue))
            {
                return nValue;
            }
            return default;
        }

        public void SetProperty(string key, int nValue)
        {
            this.customHash[key] = nValue;
            this.unit.battle.playCtrl.triggerCtrl.Broadcast(EBattleTriggerType.Battle_SetCustomProperty, ECustomProperty.Min, key, this.unit);
        }

        #endregion

        protected override void OnDispose()
        {
            this.propertyHash.Clear();
            this.customHash.Clear();
            // this.limitHash.Clear();
        }

        public override void OnCreate(TEntity entity)
        {
            this.unit = entity as Unit;
        }
    }
}